﻿#include "algorithms.h"



//1.推挤算法
//1.1 单根线段推挤
bool Algorithoms::pushLineRun(const QPointF& offset, const bool inGreed, const bool postOn) {
	if (!m_data) {
		cout << "pushLineRun: m_data is nullptr" << endl;
		return false;
	}
	//1.定义算法的输入数据
	vector<Line> polyLines_input;
	Line line_input;
	Point offset_input;
	//3.设置算法输入数据
	bool res = setPushLineData(polyLines_input, line_input, offset_input, offset);
	if (!res) return false;
	//4.创建推挤对象,设置基本参数
	SlideLine slide;
	int mode = 0;
	slide.setMode(mode);
	slide.setInGreed(inGreed);
	//5.执行算法
	int result = slide.pushSingleLine(polyLines_input, line_input, offset_input, postOn);
	//6.反馈给前端
	if (result == 0) {
		pushLineDataUpdate(polyLines_input);
		return true;
	}
	else {
		cout << "pushLineRun: pushSingleLine failed, error code= " << result << " ###" << endl;
		return false;
	}
	return true;
}
void Algorithoms::pushLineRunBegin(LineUI& line, vector<LineUI>& lines) {
	m_selectLine = line;
	m_beginLines.clear();
	for (auto& line : lines) {
		double x1 = (double)line.x1(), y1 = (double)line.y1();
		double x2 = (double)line.x2(), y2 = (double)line.y2();
		m_beginLines.emplace_back(Line(Point(x1, y1), Point(x2, y2)));
	}
	if (m_beginLines.empty()) return;
	m_beginLines[0].Pt1.locked = true;
	m_beginLines.back().Pt2.locked = true;
	m_basicData = &lines;
}
void Algorithoms::pushLineRunOver(const QPointF& offset) {
	pushLineRun(offset, m_config->m_onGrids, m_config->m_postOn);
}
//1.3 Pin推挤pushOnePt
bool Algorithoms::pushPinRun(const QPointF& offset, bool inGreed) {
	if (!m_data) {
		cout << "pushPinRun: m_data is nullptr" << endl;
		return false;
	}
	//1.定义算法的输入数据
	vector<Line> polyLines_input;
	Point pt;
	Point offset_input;
	//3.设置算法输入数据
	bool res = setPushPinData(polyLines_input, pt, offset_input, offset);

	//4.创建推挤对象,设置基本参数m_config->m_onGrids, m_config->m_postOn
	SlideLine slide;
	int mode = 1;
	slide.setMode(mode);
	slide.setInGreed(inGreed);

	//5.执行算法
	int result = slide.pushOnePt(polyLines_input, pt, offset_input);

	//6.反馈给前端
	if (result == 0) {	//推中间点
		pushLineDataUpdate(polyLines_input);
		return true;
	}
	else if (result == 1) {	//推Pin,清空布线信息
		pushLineDataUpdate(polyLines_input);
		m_data->m_wires.clear();
		m_data->m_wiresPts.clear();
		return true;
	}
	else {
		cout << "pushLineRun: pushSingleLine failed, error code= " << result << " ###" << endl;
		return false;
	}
	return true;

}
void Algorithoms::pushPinRunBegin(QPointF pt, vector<LineUI>& lines) {
	m_selectPt = pt;
	m_beginLines.clear();
	for (auto& line : lines) {
		double x1 = (double)line.x1(), y1 = (double)line.y1();
		double x2 = (double)line.x2(), y2 = (double)line.y2();
		m_beginLines.emplace_back(Line(Point(x1, y1), Point(x2, y2)));
	}
	m_basicData = &lines;
}
void Algorithoms::pushPinRunOver(const QPointF& offset) {
	pushPinRun(offset, m_config->m_onGrids);
}


//2.PPDT算法
void Algorithoms::PPDTRun(bool runInit, bool runPahtFinding) {
	;
}
void Algorithoms::PPDTRunBegin() {
	//netMap中有两个容器，0为竖线，x坐标逐条递增，对应寻路算法列号y；1为横线，y坐标逐条递增,对应寻路算法行号x
	;
}
void Algorithoms::PPDTRunOver() {
	;
}

//3.polygen算法
void Algorithoms::polyRun() {
	PolygonAlg poly(&m_points, &m_polyLines, &m_polygonss);
	poly.run();
	polyRunOver();
}
void Algorithoms::polyRunBegin() {
	if (m_data == nullptr) {
		cout << "polyRun: m_data is nullptr" << endl;
		return;
	}
	// 点赋值
	m_points.clear();
	for (const auto& pt : m_data->m_Pts) {
		m_points.emplace_back(Point(pt.x(), pt.y()));
	}
	// 多段线赋值
	m_polyLines.clear();
	for (const auto& lineUis : m_data->m_wires) {
		m_polyLines.emplace_back(vector<Line>());
		for (const auto& lineUi : lineUis) {
			m_polyLines.back().emplace_back(Line(Point(lineUi.x1(), lineUi.y1()), Point(lineUi.x2(), lineUi.y2())));
		}
	}
	// 多边形赋值
	m_polygonss.clear();
	for (const auto& m_polygons : m_data->m_polygonss) {
		m_polygonss.emplace_back(vector<vector<Line>>());
		for (const auto& lineUis : m_polygons) {
			m_polygonss.back().emplace_back(vector<Line>());
			for (const auto& lineUi : lineUis) {
				m_polygonss.back().back().emplace_back(Line(Point(lineUi.x1(), lineUi.y1()), Point(lineUi.x2(), lineUi.y2())));
			}
		}
	}
}
void Algorithoms::polyRunOver() {
	if (m_data == nullptr) {
		cout << "polyRun: m_data is nullptr" << endl;
		return;
	}
	// 点数据转化为前端数据
	vector<QPointF>& pts = m_data->m_Pts;
	pts.clear();
	for (const auto& pt : m_points) {
		pts.emplace_back(pt.x, pt.y);
	}
	// 多段线数据转化为前端数据
	vector<vector<LineUI>>& wires = m_data->m_wires;
	wires.clear();
	for (const auto& lines : m_polyLines) {
		wires.emplace_back(vector<LineUI>());
		for (const auto& line : lines) {
			wires.back().emplace_back(LineUI(line.Pt1.x, line.Pt1.y, line.Pt2.x, line.Pt2.y));
		}
	}
	// 多边形数据转化为前端数据
	vector<vector<vector<LineUI>>>& polygonss = m_data->m_polygonss;
	polygonss.clear();
	for (const auto& polygons_ui : m_polygonss) {
		polygonss.emplace_back(vector<vector<LineUI>>());
		for (const auto& polygon_ui : polygons_ui) {
			polygonss.back().emplace_back(vector<LineUI>());
			for (const auto& line : polygon_ui) {
				polygonss.back().back().emplace_back(LineUI(line.Pt1.x, line.Pt1.y, line.Pt2.x, line.Pt2.y));
			}
		}
	}
}

//私有函数,每次算法执行时,需要设置算法的各种参数
// 1.推挤算法
// 1.1推线
bool Algorithoms::setPushLineData(vector<Line>& polyLines_input, Line& line_input, Point& offset_input, const QPointF& offset_ui) {
	bool zeroOffset = offset_ui.x() == 0 && offset_ui.y() == 0;
	if (zeroOffset || m_beginLines.empty()) return false;	//偏移量为0 或 输入数据为空，结束算法
	if (m_selectLine.length() == 0) return false;	//选取的线段为零线段，结束算法

	polyLines_input = vector<Line>(m_beginLines);
	line_input = Line(Point(m_selectLine.x1(), m_selectLine.y1()), Point(m_selectLine.x2(), m_selectLine.y2()));
	offset_input = Point(offset_ui.x(), offset_ui.y());
	return true;
}
void Algorithoms::pushLineDataUpdate(vector<Line>& polyLines_input) {
	m_basicData->clear();
	for (auto& line : polyLines_input) {
		m_basicData->emplace_back(LineUI(line.Pt1.x, line.Pt1.y, line.Pt2.x, line.Pt2.y));
	}
}

// 1.2推点
bool Algorithoms::setPushPinData(vector<Line>& polyLines_input, Point& pt_input, Point& offset_input, const QPointF& offset_ui) {
	polyLines_input = vector<Line>(m_beginLines);
	pt_input = Point(m_selectPt.x(), m_selectPt.y());
	offset_input = Point(offset_ui.x(), offset_ui.y());
	return true;
}

// 2.PPDT算法